﻿using Qing.Lang;
using Qing.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Qing.Std {

    class MD5Native : Native {

        public override string Name { get; set; } = "md5";
        public override string Desc { get; set; } = "参数1-字符串，返回字符串；返回字符串的md5值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 1 || args[0].Tp != TP.Str) {
                return Expr.Err("md5函数需要一个字符串类型的参数");
            }

            string md5 = Convert.ToBase64String(MD5.HashData(Encoding.UTF8.GetBytes(args[0].Str())));
            return new Expr(TP.Str, md5);
        }

    }

    class SHA1Native : Native {
        public override string Name { get; set; } = "sha1";
        public override string Desc { get; set; } = "参数1-字符串，返回字符串；返回字符串的sha1值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 1 || args[0].Tp != TP.Str) {
                return Expr.Err("sha1函数需要一个字符串类型的参数");
            }

            string md5 = Convert.ToBase64String(SHA1.HashData(Encoding.UTF8.GetBytes(args[0].Str())));
            return new Expr(TP.Str, md5);
        }
    }

    class SHA256Native : Native {
        public override string Name { get; set; } = "sha256";
        public override string Desc { get; set; } = "参数1-字符串，返回字符串；返回字符串的sha256值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 1 || args[0].Tp != TP.Str) {
                return Expr.Err("sha256函数需要一个字符串类型的参数");
            }

            string md5 = Convert.ToBase64String(SHA256.HashData(Encoding.UTF8.GetBytes(args[0].Str())));
            return new Expr(TP.Str, md5);
        }
    }

    class SHA384Native : Native {
        public override string Name { get; set; } = "sha384";
        public override string Desc { get; set; } = "参数1-字符串，返回字符串；返回字符串的sha384值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 1 || args[0].Tp != TP.Str) {
                return Expr.Err("sha384函数需要一个字符串类型的参数");
            }

            string md5 = Convert.ToBase64String(SHA384.HashData(Encoding.UTF8.GetBytes(args[0].Str())));
            return new Expr(TP.Str, md5);
        }
    }

    class SHA512Native : Native {
        public override string Name { get; set; } = "sha512";
        public override string Desc { get; set; } = "参数1-字符串，返回字符串；返回字符串的sha512值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 1 || args[0].Tp != TP.Str) {
                return Expr.Err("sha512函数需要一个字符串类型的参数");
            }

            string md5 = Convert.ToBase64String(SHA512.HashData(Encoding.UTF8.GetBytes(args[0].Str())));
            return new Expr(TP.Str, md5);
        }
    }

    class CreateAesKey : Native {

        public override string Name { get; set; } = "生成aes密钥";
        public override string Desc { get; set; } = "可选参数1-逻辑(是否生成初始块)，命名参数-#密钥长度-265，返回字符串或字符串数组；创建随机的AES密钥";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            Aes aes = Aes.Create();
            if(namedArgs != null) {
                foreach (var item in namedArgs) {
                    if (item.List![0].Str() == "#密钥长度" && item.List![1].Tp == TP.Int) {
                        aes.KeySize = item.List![1].Int();
                    }
                }
            }
            aes.GenerateKey();
            string key = Convert.ToBase64String(aes.Key);
            if (args.Count > 0 && args[0].ToBool()) {
                aes.GenerateIV();
                string iv = Convert.ToBase64String(aes.IV);
                List<Expr> list = new List<Expr>();
                list.Add(new Expr(TP.Str, key));
                list.Add(new Expr(TP.Str, iv));
                return new Expr(TP.Arr, list);
            } else {
                return new Expr(TP.Str, key);
            }

        }

    }

    class AesEncrypt : Native {

        public override string Name { get; set; } = "aes加密";
        public override string Desc { get; set; } = "参数1-字符串(待加密数据)，参数2-字符串(密钥)，可选参数3-字符串(初始块)，返回字符串；使用AES算法加密数据";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 2) {
                return Expr.Err("ase加密函数的参数不足");
            }
            if (args[0].Tp != TP.Str || args[1].Tp != TP.Str) {
                return Expr.Err("ase加密函数的参数类型错误");
            }

            string data = args[0].Str();
            string key = args[1].Str();
            string iv = SecurityUtil.DEFAULT_AES_IV;

            if (args.Count > 2 && args[2].Tp == TP.Str) {
                iv = args[2].Str();
            }

            return new Expr(TP.Str, SecurityUtil.AesEncrypt(data, key, iv));

        }

    }

    class AesDecrypt : Native {
        public override string Name { get; set; } = "aes解密";
        public override string Desc { get; set; } = "参数1-字符串(加密后数据)，参数2-字符串(密钥)，可选参数3-字符串(初始块)，返回字符串；使用AES算法解密数据";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 2) {
                return Expr.Err("ase加密函数的参数不足");
            }
            if (args[0].Tp != TP.Str || args[1].Tp != TP.Str) {
                return Expr.Err("ase加密函数的参数类型错误");
            }

            string data = args[0].Str();
            string key = args[1].Str();
            string iv = SecurityUtil.DEFAULT_AES_IV;

            if (args.Count > 2 && args[2].Tp == TP.Str) {
                iv = args[2].Str();
            }

            return new Expr(TP.Str, SecurityUtil.AesDecrypt(data, key, iv));

        }

    }


    class CreateDesKey : Native {

        public override string Name { get; set; } = "生成des密钥";
        public override string Desc { get; set; } = "可选参数1-逻辑(是否生成初始块)，命名参数-#密钥长度=64，返回字符串或字符串数组；生成随机的DES密钥";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            DES des = DES.Create();
            if (namedArgs != null) {
                foreach (var item in namedArgs) {
                    if (item.List![0].Str() == "#密钥长度" && item.List![1].Tp == TP.Int) {
                        des.KeySize = item.List![1].Int();
                    }
                }
            }
            des.GenerateKey();
            string key = Convert.ToBase64String(des.Key);
            if (args.Count > 0 && args[0].ToBool()) {
                des.GenerateIV();
                string iv = Convert.ToBase64String(des.IV);
                List<Expr> list = new List<Expr>();
                list.Add(new Expr(TP.Str, key));
                list.Add(new Expr(TP.Str, iv));
                return new Expr(TP.Arr, list);
            } else {
                return new Expr(TP.Str, key);
            }

        }

    }


    class DesEncrypt : Native {

        public override string Name { get; set; } = "des加密";
        public override string Desc { get; set; } = "参数1-字符串(待加密数据)，参数2-字符串(密钥)，可选参数3-字符串(初始块)，返回字符串；使用DES算法加密数据";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 2) {
                return Expr.Err("ase加密函数的参数不足");
            }
            if (args[0].Tp != TP.Str || args[1].Tp != TP.Str) {
                return Expr.Err("ase加密函数的参数类型错误");
            }

            string data = args[0].Str();
            string key = args[1].Str();
            string iv = SecurityUtil.DEFAULT_DES_IV;

            if (args.Count > 2 && args[2].Tp == TP.Str) {
                iv = args[2].Str();
            }

            return new Expr(TP.Str, SecurityUtil.DesEncrypt(data, key, iv));

        }

    }


    class DesDecrypt : Native {
        public override string Name { get; set; } = "des解密";
        public override string Desc { get; set; } = "参数1-字符串(加密后数据)，参数2-字符串(密钥)，可选参数3-字符串(初始块)，返回字符串；使用DES算法解密数据";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 2) {
                return Expr.Err("ase加密函数的参数不足");
            }
            if (args[0].Tp != TP.Str || args[1].Tp != TP.Str) {
                return Expr.Err("ase加密函数的参数类型错误");
            }

            string data = args[0].Str();
            string key = args[1].Str();
            string iv = SecurityUtil.DEFAULT_DES_IV;

            if (args.Count > 2 && args[2].Tp == TP.Str) {
                iv = args[2].Str();
            }

            return new Expr(TP.Str, SecurityUtil.DesDecrypt(data, key, iv));

        }
    }


    class CreateRsaKey : Native {
        public override string Name { get; set; } = "生成rsa密钥";
        public override string Desc { get; set; } = "可选参数1-整数，返回字符串数组；创建随机的RSA密钥，可选参数1为公钥长度，默认为1024";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            int keySize = 1024;
            if(args.Count > 0 && args[0].Tp == TP.Int) {
                keySize = args[0].Int();
            }
            RSA rsa = RSA.Create(keySize);
            string pub = rsa.ToXmlString(false);
            string pri = rsa.ToXmlString(true);
            List<Expr> list = new List<Expr>();
            list.Add(new Expr(TP.Str, pub));
            list.Add(new Expr(TP.Str, pri));
            return new Expr(TP.Arr, list);
        }
    }


    class RsaEncrypt : Native {
        public override string Name { get; set; } = "rsa加密";
        public override string Desc { get; set; } = "参数1-字符串(待加密数据)，参数2-字符串(密钥)，返回字符串；使用RSA算法加密数据";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 2) {
                return Expr.Err("rsa加密函数的参数不足");
            }
            if (args[0].Tp != TP.Str || args[1].Tp != TP.Str) {
                return Expr.Err("rsa加密函数的参数类型错误");
            }

            string data = args[0].Str();
            string key = args[1].Str();

            return new Expr(TP.Str, SecurityUtil.RsaEncrypt(data, key));
        }

    }


    class RsaDecrypt : Native {
        public override string Name { get; set; } = "rsa解密";
        public override string Desc { get; set; } = "参数1-字符串(待解密数据)，参数2-字符串(密钥)，返回字符串；使用RSA算法解密数据";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count < 2) {
                return Expr.Err("rsa解密函数的参数不足");
            }
            if (args[0].Tp != TP.Str || args[1].Tp != TP.Str) {
                return Expr.Err("rsa解密函数的参数类型错误");
            }

            string data = args[0].Str();
            string key = args[1].Str();

            return new Expr(TP.Str, SecurityUtil.RsaDecrypt(data, key));
        }

    }



}
